home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1308.dms / var1308.adf / DNET2_10.LHA / DNet / Amiga / Sourcen.lha / doshand / nfs-handler.c < prev    next >
C/C++ Source or Header  |  1993-01-14  |  26KB  |  1,038 lines

  1.  
  2. /*
  3.  *  NFS-HANDLER.C    V1.11    27-June-89
  4.  *
  5.  *  DNet DOS level NFS handler.
  6.  *
  7.  *  By Matthew Dillon.
  8.  *
  9.  *  This handler converts DOS packets into a form suitable for transmission
  10.  *  over a DNet link to a remote server which will execute the operations.
  11.  */
  12.  
  13. #include "dos.h"
  14. #include <exec/alerts.h>
  15.  
  16. /*
  17.  *  Since this code might be called several times in a row without being
  18.  *  unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!!  This also goes
  19.  *  for any global/static assignments that might be changed by running the
  20.  *  code.
  21.  */
  22.  
  23. PROC    *DosProc;   /*    Our Process                    */
  24. DEVNODE *DosNode;   /*    Our DOS node.. created by DOS for us        */
  25. DEVLIST *DevList;   /*    Device List structure for our volume node   */
  26.  
  27. void    *SysBase;   /*    EXEC library base            */
  28. /*
  29. void    *DResBase;
  30. */
  31.  
  32. DOSLIB    *DOSBase;   /*    DOS library base for debug process    */
  33. MLIST    FHBase;     /*    Open Files                */
  34. MLIST    LCBase;     /*    Open Locks                */
  35.  
  36. long    TotalBytes; /*    total bytes of data in filesystem    */
  37.  
  38. void    *CHan;        /*    DNet channel                */
  39. HANDLE    RFRoot;
  40.  
  41. char    TmpBuf[256];
  42.  
  43. #ifdef DEBUG
  44. short DBDisable = 0;    /*  Debug code                    */
  45. #endif
  46.  
  47.  
  48. HANDLE *AllocHandle();
  49.  
  50. /*
  51.  *  Don't call the entry point main().  This way, if you make a mistake
  52.  *  with the compile options you'll get a link error.
  53.  */
  54.  
  55. void __saveds noname ARGS((void));
  56.  
  57. void returnpacket ARGS((PACKET *));
  58. int packetsqueued ARGS((void));
  59. HANDLE *GetHandleForLock ARGS((LOCK *));
  60. void *GetLockForHandle ARGS((HANDLE *));
  61. HANDLE *AllocHandle ARGS((char *, RtOpen *));
  62. void FreeHandle ARGS((HANDLE *));
  63. void *dosalloc ARGS((ulong));
  64. void dosfree ARGS((ulong *));
  65. char *bstos ARGS((ubyte *));
  66. char *skipdevice ARGS((char *));
  67. int DoNetworkOp ARGS((char, void *, int, void *, int, void *, int));
  68.  
  69. void __saveds
  70. noname()
  71. {
  72.     reg PACKET    *packet;
  73.     reg short    error;
  74.     MSG     *msg;
  75.     ubyte   notdone;
  76.     void    *tmp;
  77.  
  78. #ifndef LATTICE
  79.     mygeta4();
  80. #endif
  81.  
  82.     /*
  83.      *    Initialize all global variables.  SysBase MUST be initialized before
  84.      *    we can make Exec calls.
  85.      */
  86.  
  87.     TotalBytes = 0;
  88.     SysBase = *(void **)4;
  89.     DOSBase = (void *)OpenLibrary("dos.library",0);
  90.     /*
  91.     DResBase= OpenLibrary("dres.library",0);
  92.     */
  93.     DosProc = (PROC *)FindTask(NULL);
  94.     CHan = 0;
  95.     {
  96.     WaitPort(&DosProc->pr_MsgPort);         /*  Get Startup Packet  */
  97.     msg = GetMsg(&DosProc->pr_MsgPort);
  98.     packet = (PACKET *)msg->mn_Node.ln_Name;
  99.  
  100.     /*
  101.      *  Loading DosNode->dn_Task causes DOS *NOT* to startup a new
  102.      *  instance of the device driver for every reference.    E.G. if
  103.      *  you were writing a CON device you would want this field to
  104.      *  be NULL.
  105.      */
  106.  
  107.     if (DOSBase /*&& DResBase*/) {
  108.         DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
  109.         register DEVLIST *dl = dosalloc(sizeof(DEVLIST));
  110.  
  111.         DosNode = BTOC(packet->dp_Arg3);
  112.         DosNode->dn_Task = &DosProc->pr_MsgPort;
  113.  
  114.         /*
  115.          *    Create Volume node and add to the device list.    This will
  116.          *    cause the WORKBENCH to recognize us as a disk.    If we don't
  117.          *    create a Volume node, Wb will not recognize us.  However,
  118.          *    we are a RAM: disk, Volume node or not.
  119.          */
  120.  
  121.         DevList = dl;
  122.         dl->dl_Type = DLT_VOLUME;
  123.         dl->dl_Task = &DosProc->pr_MsgPort;
  124.         dl->dl_DiskType = ID_DOS_DISK;
  125.         dl->dl_Name = (BSTR)DosNode->dn_Name;
  126.         dl->dl_Next = di->di_DevInfo;
  127.         di->di_DevInfo = (long)CTOB(dl);
  128.  
  129.         packet->dp_Res1 = DOS_TRUE;
  130.         packet->dp_Res2 = 0;
  131.     } else {                /*    couldn't open dos.library   */
  132.         packet->dp_Res1 = DOS_FALSE;
  133.         returnpacket(packet);
  134.         return;                /*    exit process            */
  135.     }
  136.     returnpacket(packet);
  137.     }
  138.  
  139.     /*    Initialize  RAM disk    */
  140. #ifdef DEBUG
  141.     dbinit();
  142. #endif
  143.  
  144.     {
  145.     NewList((LIST *)&FHBase);                   /*  more globals    */
  146.     NewList((LIST *)&LCBase);
  147.  
  148.     BZero(&RFRoot, sizeof(RFRoot));
  149.     DateStamp((long *)&RFRoot.Date);
  150.     RFRoot.Type = FILE_DIR;
  151.     RFRoot.Name = "Root";
  152.     }
  153.  
  154.     /*
  155.      *    Here begins the endless loop, waiting for requests over our
  156.      *    message port and executing them.  Since requests are sent over
  157.      *    our message port, this precludes being able to call DOS functions
  158.      *    ourselves (that is why the debugging routines are a separate process)
  159.      */
  160.  
  161. top:
  162.     for (notdone = 1; notdone;) {
  163.     WaitPort(&DosProc->pr_MsgPort);
  164.     while (msg = GetMsg(&DosProc->pr_MsgPort)) {
  165.         packet = (PACKET *)msg->mn_Node.ln_Name;
  166.         packet->dp_Res1 = DOS_TRUE;
  167.         packet->dp_Res2 = 0;
  168.         error = 0;
  169.  
  170.         if (!CHan) {            /*  attempt to open server channel      */
  171.         CHan = DOpen(NULL, PORT_NFS, -80, -80);
  172.         if (!CHan) {        /*  otherwise giveup!                   */
  173.             notdone = 0;
  174.             goto fail;
  175.         }
  176.         }
  177.  
  178. #ifdef DEBUG
  179.         dbprintf("ACTION %ld\n", packet->dp_Type);
  180. #endif
  181.         switch(packet->dp_Type) {
  182.         case ACTION_DIE:        /*    attempt to die?             */
  183.         notdone = 0;        /*    try to die                */
  184.         break;
  185.         case ACTION_OPENRW:     /*    FileHandle,Lock,Name        Bool    */
  186.         case ACTION_OPENOLD:    /*    FileHandle,Lock,Name        Bool    */
  187.         case ACTION_OPENNEW:    /*    FileHandle,Lock,Name        Bool    */
  188.         {
  189.             OpOpen    opkt;
  190.             RtOpen    rpkt;
  191.             short    r;
  192.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg3));
  193.             HANDLE    *handle;
  194.  
  195.             opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg2)->Handle;
  196.             opkt.Modes = packet->dp_Type;
  197.  
  198.             r = DoNetworkOp('O',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  199.             if (r) {
  200.             error = ERROR_OBJECT_IN_USE;
  201.             } else if (rpkt.Handle == -1) {
  202.             error = ERROR_OBJECT_NOT_FOUND;
  203.             } else if (rpkt.Type > 0) {     /* can't open dir */
  204.             OpClose  opkt;
  205.  
  206.             opkt.Handle = rpkt.Handle;
  207.             DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
  208.             error = ERROR_OBJECT_WRONG_TYPE;
  209.             } else {
  210.             if (name[0] == 0)
  211.                 name = GetHandleForLock((LOCK *)packet->dp_Arg2)->Name;
  212.             handle = AllocHandle(name, &rpkt);
  213.             ((FH *)BTOC(packet->dp_Arg1))->fh_Arg1 = (long)handle;
  214.             }
  215.         }
  216.         break;
  217.         case ACTION_READ:        /*     FHArg1,CPTRBuffer,Length   ActLength  */
  218.         {
  219.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  220.             OpRead    opkt;
  221.             RtRead    rpkt;
  222.             short    err;
  223.  
  224.             opkt.Handle = handle->Handle;
  225.             opkt.Bytes        = packet->dp_Arg3;
  226.  
  227.             err = DoNetworkOp('R',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  228.             if (err)
  229.             rpkt.Bytes = -1;
  230.             if (rpkt.Bytes > 0 && rpkt.Bytes <= opkt.Bytes)
  231.             DRead(CHan, (void *)packet->dp_Arg2, rpkt.Bytes);
  232.             packet->dp_Res1 = rpkt.Bytes;
  233.         }
  234.         break;
  235.         case ACTION_WRITE:        /*     FHArg1,CPTRBuffer,Length   ActLength  */
  236.         {
  237.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  238.             OpWrite    opkt;
  239.             RtWrite    rpkt;
  240.             short    err;
  241.  
  242.             opkt.Handle = handle->Handle;
  243.             opkt.Bytes        = packet->dp_Arg3;
  244.  
  245.             err = DoNetworkOp('W',&opkt,sizeof(opkt),(void *)packet->dp_Arg2,packet->dp_Arg3,&rpkt,sizeof(rpkt));
  246.  
  247.             if (err)
  248.             rpkt.Bytes = -1;
  249.             packet->dp_Res1 = rpkt.Bytes;
  250.         }
  251.         break;
  252.         case ACTION_CLOSE:        /*     FHArg1             Bool:TRUE  */
  253.         {
  254.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  255.             OpClose    opkt;
  256.  
  257.             if (packet->dp_Arg1 == NULL || handle->Magic != MAGIC) {
  258.             Alert(AT_Recovery|0, (char *)0x12345555);
  259.             } else {
  260.             opkt.Handle = handle->Handle;
  261.  
  262.             DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
  263.             FreeHandle(handle);
  264.             }
  265.         }
  266.         if (!GetHead(&FHBase))
  267.             notdone = 0;
  268.         break;
  269.         case ACTION_SEEK:        /*     FHArg1,Position,Mode        OldPosition*/
  270.         {
  271.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  272.             OpSeek  opkt;
  273.             RtSeek  rpkt;
  274.             short   err;
  275.  
  276.             opkt.Handle = handle->Handle;
  277.             opkt.Offset = packet->dp_Arg2;
  278.             opkt.How    = packet->dp_Arg3 + 1;
  279.  
  280.             err = DoNetworkOp('S',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  281.             if (err)
  282.             rpkt.NewOffset = -1;
  283.             if (rpkt.NewOffset < 0)
  284.             error = ERROR_SEEK_ERROR;
  285.             else
  286.             packet->dp_Res1 = rpkt.OldOffset;
  287.         }
  288.         break;
  289.         case ACTION_EXAMINE_NEXT: /*   Lock,Fib              Bool     */
  290.         {
  291.             HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  292.             register FIB *fib = BTOC(packet->dp_Arg2);
  293.             OpNextDir opkt;
  294.             RtNextDir rpkt;
  295.             short err;
  296.  
  297. #ifdef DEBUG
  298.             dbprintf("FIB = %08lx\n", fib);
  299. #endif
  300.             if (handle->Type < 0) {
  301.             error = ERROR_OBJECT_WRONG_TYPE;
  302.             break;
  303.             }
  304.  
  305.             opkt.Handle = handle->Handle;
  306.             opkt.Index    = fib->fib_DiskKey;
  307.             err = DoNetworkOp('N',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  308.             if (err || rpkt.Handle == -1) {
  309.             error = ERROR_NO_MORE_ENTRIES;
  310.             } else {    /* not a real file handle, just info & name */
  311.             unsigned char fn;
  312.  
  313.             if (DRead(CHan, &fn, 1) != 1)
  314.                 TmpBuf[fn = 0] = 0;
  315.             if (DRead(CHan, TmpBuf, fn) != fn)
  316.                 TmpBuf[fn = 0] = 0;
  317.             ++fib->fib_DiskKey;    /*  next key */
  318.             fib->fib_DirEntryType = rpkt.Type;
  319.             fib->fib_Protection = rpkt.Prot;
  320.             fib->fib_EntryType = NULL;
  321.             fib->fib_Size = rpkt.Size;
  322.             fib->fib_NumBlocks = rpkt.Size >> 9;
  323.             if (strlen(TmpBuf) >= sizeof(fib->fib_FileName) - 2) {
  324.                 fib->fib_FileName[0] = 1;
  325.                 fib->fib_FileName[1] = '?';
  326.                 fib->fib_FileName[2] = 0;
  327.             } else {
  328.                 strcpy(fib->fib_FileName+1, TmpBuf);
  329.                 fib->fib_FileName[0] = strlen(TmpBuf);
  330.             }
  331.             fib->fib_Comment[0] = 0;
  332.             fib->fib_Comment[1] = 0;
  333.             fib->fib_Date = rpkt.Date;
  334.             }
  335.         }
  336.         break;
  337.         case ACTION_EXAMINE_OBJECT: /*   Lock,Fib            Bool       */
  338.         {
  339.             HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  340.             register FIB *fib = BTOC(packet->dp_Arg2);
  341.  
  342. #ifdef DEBUG
  343.             dbprintf("FIB = %08lx\n", fib);
  344. #endif
  345.             fib->fib_DiskKey = 0;
  346.             fib->fib_DirEntryType = handle->Type;
  347.             /*
  348.              *    fib->fib_FileName bcpl type string
  349.              */
  350.             fib->fib_Protection = handle->Prot;
  351.             fib->fib_EntryType = NULL;
  352.             fib->fib_Size = handle->Size;
  353.             fib->fib_NumBlocks = handle->Size >> 9;
  354.  
  355.             if (strlen(handle->Name) >= sizeof(fib->fib_FileName) - 2) {
  356.             fib->fib_FileName[0] = 1;
  357.             fib->fib_FileName[1] = '?';
  358.             fib->fib_FileName[2] = 0;
  359.             } else {
  360.             strcpy(fib->fib_FileName+1, handle->Name);
  361.             fib->fib_FileName[0] = strlen(handle->Name);
  362.             }
  363.             fib->fib_Comment[0] = 0;
  364.             fib->fib_Comment[1] = 0;
  365.             fib->fib_Date = handle->Date;
  366.         }
  367.         break;
  368.         case ACTION_INFO:        /*    Lock, InfoData      Bool:TRUE    */
  369.         tmp = BTOC(packet->dp_Arg2);
  370.         error = -1;
  371.         /*  fall through    */
  372.         case ACTION_DISK_INFO:  /*    InfoData      Bool:TRUE    */
  373.         {
  374.             register INFODATA *id;
  375.  
  376.             /*
  377.              *    Note:    id_NumBlocks is never 0, but only to get
  378.              *    around a bug I found in my shell (where I divide
  379.              *    by id_NumBlocks).  Other programs probably break
  380.              *    as well.
  381.              */
  382.  
  383.             (error) ? (id = tmp) : (id = BTOC(packet->dp_Arg1));
  384.             error = 0;
  385.             BZero(id, sizeof(*id));
  386.             id->id_DiskState = ID_VALIDATED;
  387.             id->id_NumBlocks     = (TotalBytes >> 9) + 1;
  388.             id->id_NumBlocksUsed = (TotalBytes >> 9) + 1;
  389.             id->id_BytesPerBlock = 512;
  390.             id->id_DiskType = ID_DOS_DISK;
  391.             id->id_VolumeNode = (long)CTOB(DosNode);
  392.             id->id_InUse = (long)GetHead(&LCBase);
  393.         }
  394.         break;
  395.         case ACTION_PARENT:     /*     Lock                ParentLock */
  396.         {
  397.             HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  398.             OpParent    opkt;
  399.             RtParent    rpkt;
  400.             short    err;
  401.  
  402.             opkt.Handle = handle->Handle;
  403.  
  404.             err = DoNetworkOp('P',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  405.             if (err)
  406.             rpkt.Handle = NULL;
  407.             if (rpkt.Handle == -1) {
  408.             error = ERROR_OBJECT_NOT_FOUND;
  409.             } else {    /*  create a file handle and return a lock */
  410.             HANDLE *newhandle;
  411.             unsigned char fn;
  412.  
  413.             if (DRead(CHan, &fn, 1) != 1)
  414.                 TmpBuf[fn = 0] = 0;
  415.             if (DRead(CHan, TmpBuf, fn) != fn)
  416.                 TmpBuf[fn = 0] = 0;
  417.             newhandle = AllocHandle(TmpBuf, &rpkt);
  418.             packet->dp_Res1 = (long)GetLockForHandle(newhandle);
  419.             }
  420.         }
  421.         break;
  422.         case ACTION_DELETE_OBJECT: /*Lock,Name            Bool       */
  423.         {
  424.             OpDelete    opkt;
  425.             RtDelete    rpkt;
  426.             short    err;
  427.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
  428.  
  429.             opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
  430.  
  431.             err = DoNetworkOp('D',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  432.             if (err || rpkt.Error)
  433.             error = ERROR_OBJECT_NOT_FOUND;
  434.         }
  435.         break;
  436.         case ACTION_CREATE_DIR: /*     Lock,Name            Lock       */
  437.         {
  438.             OpCreateDir opkt;
  439.             RtCreateDir rpkt;
  440.             short    err;
  441.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
  442.  
  443.             opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
  444.  
  445.             err = DoNetworkOp('M',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  446.             if (err)
  447.             rpkt.Handle = NULL;
  448.             if (rpkt.Handle == -1) {
  449.             error = ERROR_OBJECT_EXISTS;
  450.             } else {    /*  create a file handle and return a lock */
  451.             HANDLE *newhandle = AllocHandle(name, &rpkt);
  452.  
  453.             packet->dp_Res1 = (long)GetLockForHandle(newhandle);
  454.             }
  455.         }
  456.         break;
  457.         case ACTION_LOCATE_OBJECT:    /*   Lock,Name,Mode        Lock       */
  458.         {
  459.             OpOpen    opkt;
  460.             RtOpen    rpkt;
  461.             short    err;
  462.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
  463.             HANDLE    *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  464.  
  465.             opkt.DirHandle = handle->Handle;
  466.             opkt.Modes = 1005;
  467.  
  468.             err = DoNetworkOp('O',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  469.             if (err) {
  470.             error = ERROR_OBJECT_IN_USE;
  471.             } else if (rpkt.Handle == -1) {
  472.             error = ERROR_OBJECT_NOT_FOUND;
  473.             } else {
  474.             HANDLE *newhandle;
  475.             if (name[0] == 0)
  476.                 name = handle->Name;
  477.  
  478.             newhandle = AllocHandle(name, &rpkt);
  479.             packet->dp_Res1 = (long)GetLockForHandle(newhandle);
  480.             }
  481.         }
  482.         break;
  483.         case ACTION_COPY_DIR:   /*     Lock,                Lock       */
  484.         {
  485.             OpDup    opkt;
  486.             RtDup    rpkt;
  487.             short    err;
  488.             HANDLE    *oldhandle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  489.  
  490.             opkt.Handle = oldhandle->Handle;
  491.  
  492.             err = DoNetworkOp('d',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  493.             if (err) {
  494.             error = ERROR_OBJECT_IN_USE;
  495.             } else if (rpkt.Handle == -1) {
  496.             error = ERROR_OBJECT_NOT_FOUND;
  497.             } else {
  498.             HANDLE *handle = AllocHandle(oldhandle->Name, &rpkt);
  499.  
  500.             packet->dp_Res1 = (long)GetLockForHandle(handle);
  501.             }
  502.         }
  503.         break;
  504.         case ACTION_FREE_LOCK:  /*     Lock,                Bool       */
  505.         {
  506.             HANDLE  *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  507.             OpClose    opkt;
  508.  
  509.             opkt.Handle = handle->Handle;
  510.  
  511.             DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
  512.             FreeHandle(handle);
  513.         }
  514.         break;
  515.         case ACTION_SET_PROTECT:/*     -,Lock,Name,Mask       Bool       */
  516.         error = ERROR_ACTION_NOT_KNOWN;
  517.         break;
  518.         case ACTION_SET_COMMENT:/*     -,Lock,Name,Comment       Bool       */
  519.         error = ERROR_ACTION_NOT_KNOWN;
  520.         break;
  521.         case ACTION_RENAME_OBJECT:/* SLock,SName,DLock,DName    Bool       */
  522.         {
  523.             OpRename    opkt;
  524.             RtRename    rpkt;
  525.             short    err;
  526.             char    *name1= skipdevice(bstos((ubyte *)packet->dp_Arg2));
  527.             char    *name2= skipdevice(bstos((ubyte *)packet->dp_Arg4));
  528.             short    len1 = strlen(name1);
  529.             short    len2 = strlen(name2);
  530.             char    *name = AllocMem(len1+len2+2, MEMF_PUBLIC);
  531.  
  532.             opkt.DirHandle1 = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
  533.             opkt.DirHandle2 = GetHandleForLock((LOCK *)packet->dp_Arg3)->Handle;
  534.             strcpy(name, name1);
  535.             strcpy(name+len1+1,name2);
  536.  
  537.             err = DoNetworkOp('r',&opkt,sizeof(opkt),name,len1+len2+2,&rpkt,sizeof(rpkt));
  538.             FreeMem(name, len1+len2+2);
  539.             if (err) {
  540.             error = ERROR_OBJECT_IN_USE;
  541.             } else if (rpkt.Error) {
  542.             error = ERROR_OBJECT_NOT_FOUND;
  543.             }
  544.         }
  545.         break;
  546.         /*
  547.          *    A few other packet types which we do not support
  548.          */
  549.         case ACTION_INHIBIT:    /*     Bool                Bool       */
  550.         /*  Return success for the hell of it    */
  551.         break;
  552.         case ACTION_RENAME_DISK:/*     BSTR:NewName            Bool       */
  553.         case ACTION_MORECACHE:  /*     #BufsToAdd            Bool       */
  554.         case ACTION_WAIT_CHAR:  /*     Timeout, ticks         Bool       */
  555.         case ACTION_FLUSH:        /*     writeout bufs, disk motor off           */
  556.         case ACTION_RAWMODE:    /*     Bool(-1:RAW 0:CON)         OldState   */
  557.         default:
  558. fail:
  559.         error = ERROR_ACTION_NOT_KNOWN;
  560.         break;
  561.         }
  562.         if (packet) {
  563.         if (error) {
  564.             packet->dp_Res1 = DOS_FALSE;
  565.             packet->dp_Res2 = error;
  566.         }
  567.         returnpacket(packet);
  568.         }
  569.     }
  570.     }
  571.     Delay(50);      /*  I wanna even see the debug message! */
  572.     Forbid();
  573.     if (packetsqueued() || GetHead(&FHBase)) {
  574.     Permit();
  575.     goto top;        /*  sorry... can't exit     */
  576.     }
  577.  
  578.     /*
  579.      *    Causes a new process to be created on next reference
  580.      */
  581.  
  582.     DosNode->dn_Task = FALSE;
  583.  
  584.     /*
  585.      *    Remove Volume entry.  Since DOS uses singly linked lists, we
  586.      *    must (ugg) search it manually to find the link before our
  587.      *    Volume entry.
  588.      */
  589.  
  590.     {
  591.     DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
  592.     register DEVLIST *dl;
  593.     register void *dlp;
  594.  
  595.     dlp = &di->di_DevInfo;
  596.     for (dl = BTOC(di->di_DevInfo); dl && dl != DevList; dl = BTOC(dl->dl_Next))
  597.         dlp = &dl->dl_Next;
  598.     if (dl == DevList) {
  599.         *(BPTR *)dlp = dl->dl_Next;
  600.         dosfree((ulong *)dl);
  601.     } else {
  602.         ;
  603.     }
  604.     }
  605.  
  606.     /*
  607.      *    closedown, fall of the end of the world
  608.      *
  609.      *    (which is how you kill yourself if a PROCESS.  A TASK would have
  610.      *    had to RemTask(NULL) itself).
  611.      */
  612.  
  613.     if (CHan)
  614.     DClose(CHan);
  615.     CHan = 0;
  616. #ifdef DEBUG
  617.     dbuninit();
  618. #endif
  619.     CloseLibrary((LIB *)DOSBase);
  620.     /*
  621.     CloseLibrary(DResBase);
  622.     */
  623. }
  624.  
  625.  
  626. /*
  627.  *  PACKET ROUTINES.    Dos Packets are in a rather strange format as you
  628.  *  can see by this and how the PACKET structure is extracted in the
  629.  *  GetMsg() of the main routine.
  630.  */
  631.  
  632. void
  633. returnpacket(packet)
  634. PACKET *packet;
  635. {
  636.     register struct Message *mess;
  637.     register struct MsgPort *replyport;
  638.  
  639.     replyport             = packet->dp_Port;
  640.     mess             = packet->dp_Link;
  641.     packet->dp_Port         = &DosProc->pr_MsgPort;
  642.     mess->mn_Node.ln_Name    = (char *)packet;
  643.     mess->mn_Node.ln_Succ    = NULL;
  644.     mess->mn_Node.ln_Pred    = NULL;
  645.     PutMsg(replyport, mess);
  646. }
  647.  
  648. /*
  649.  *  Are there any packets queued to our device?
  650.  */
  651.  
  652. int
  653. packetsqueued()
  654. {
  655.     return ((void *)DosProc->pr_MsgPort.mp_MsgList.lh_Head !=
  656.         (void *)&DosProc->pr_MsgPort.mp_MsgList.lh_Tail);
  657. }
  658.  
  659. /*
  660.  *  Handle structure, locks, and manipulation.
  661.  */
  662.  
  663. HANDLE *
  664. GetHandleForLock(block)
  665. LOCK *block;
  666. {
  667.     register LOCK *lock = BTOC(block);
  668.     register HANDLE *handle;
  669.  
  670. #ifdef DEBUG
  671.     dbprintf("GetHandleForLock: %08lx ", lock);
  672. #endif
  673.     if (lock) {
  674.     handle = (HANDLE *)lock->fl_Key;
  675. #ifdef DEBUG
  676.     dbprintf("Handle=%08lx (h=$%08lx)\n", handle, handle->Handle);
  677. #endif
  678.     if (handle->Magic == MAGIC)
  679.         return(handle);
  680.     Alert(AT_Recovery|1, (char *)handle);
  681.     }
  682. #ifdef DEBUG
  683.     dbprintf("\n");
  684. #endif
  685.     /*Alert(AT_Recovery|2, (char *)-2);*/
  686.     return(&RFRoot);
  687. }
  688.  
  689. void *
  690. GetLockForHandle(handle)
  691. HANDLE *handle;
  692. {
  693.     register LOCK *lock = handle->Lock;
  694.     register LOCKLINK *ln;
  695.  
  696. #ifdef DEBUG
  697.     dbprintf("GetLockForHandle: %08lx ", handle);
  698. #endif
  699.     if (!lock) {
  700.     lock = dosalloc(sizeof(LOCK));
  701. #ifdef DEBUG
  702.     dbprintf("(allocate) %08lx\n", lock);
  703. #endif
  704.     ln = AllocMem(sizeof(LOCKLINK), MEMF_PUBLIC|MEMF_CLEAR);
  705.     AddHead((LIST *)&LCBase,(NODE *)ln);
  706.     ln->Lock = lock;
  707.     lock->fl_Link = (long)ln;
  708.     lock->fl_Key = (long)handle;
  709.     lock->fl_Access = ACCESS_READ;
  710.     lock->fl_Task= &DosProc->pr_MsgPort;
  711.     lock->fl_Volume = (BPTR)CTOB(DosNode);
  712.  
  713.     handle->Lock = lock;
  714.     }
  715. #ifdef DEBUG
  716.     dbprintf("Lock=%08lx\n", lock);
  717. #endif
  718.     return((void *)CTOB(lock));
  719. }
  720.  
  721. HANDLE *
  722. AllocHandle(name, rpkt)
  723. char *name;
  724. RtOpen *rpkt;
  725. {
  726.     HANDLE *handle;
  727.     register char *ptr;
  728.  
  729.     for (ptr = name + strlen(name) - 1; ptr >= name && *ptr != '/'; --ptr);
  730.     ++ptr;
  731.  
  732.     handle = AllocMem(sizeof(HANDLE), MEMF_PUBLIC|MEMF_CLEAR);
  733.     handle->Magic = MAGIC;
  734.     handle->Handle= rpkt->Handle;
  735.     handle->Type = rpkt->Type;
  736.     handle->Prot = rpkt->Prot;
  737.     handle->Size = rpkt->Size;
  738.     handle->Name = AllocMem(strlen(ptr)+1, MEMF_PUBLIC);
  739.     handle->Date = rpkt->Date;
  740.     strcpy(handle->Name, ptr);
  741.     AddHead((LIST *)&FHBase, (NODE *)handle);
  742.  
  743. #ifdef DEBUG
  744.     dbprintf("AllocHandle: %08lx '%s' h=$%08lx\n", handle, ptr, handle->Handle);
  745. #endif
  746.     return(handle);
  747. }
  748.  
  749. void
  750. FreeHandle(handle)
  751. HANDLE *handle;
  752. {
  753. #ifdef DEBUG
  754.     dbprintf("FreeHandle: %08lx %08lx\n", handle, handle->Lock);
  755. #endif
  756.     if (handle->Lock) {
  757.     register LOCK *lock = handle->Lock;
  758.     Remove((NODE *)lock->fl_Link);
  759.     FreeMem((void *)lock->fl_Link, sizeof(LOCKLINK));
  760.     dosfree((ulong *)lock);
  761.     }
  762.     Remove((NODE *)handle);
  763.     handle->Magic = 0;
  764.     FreeMem(handle->Name, strlen(handle->Name)+1);
  765.     FreeMem(handle, sizeof(HANDLE));
  766. }
  767.  
  768. /*
  769.  *  DOS MEMORY ROUTINES
  770.  *
  771.  *  DOS makes certain assumptions about LOCKS.    A lock must minimally be
  772.  *  a FileLock structure, with additional private information after the
  773.  *  FileLock structure.  The longword before the beginning of the structure
  774.  *  must contain the length of structure + 4.
  775.  *
  776.  *  NOTE!!!!! The workbench does not follow the rules and assumes it can
  777.  *  copy lock structures.  This means that if you want to be workbench
  778.  *  compatible, your lock structures must be EXACTLY sizeof(struct FileLock).
  779.  */
  780.  
  781. void *
  782. dosalloc(bytes)
  783. reg ulong bytes;
  784. {
  785.     reg ulong *ptr;
  786.  
  787.     bytes += 4;
  788.     ptr = AllocMem(bytes, MEMF_PUBLIC|MEMF_CLEAR);
  789.     *ptr = bytes;
  790.     return(ptr+1);
  791. }
  792.  
  793. void
  794. dosfree(ptr)
  795. register ulong *ptr;
  796. {
  797.     --ptr;
  798.     FreeMem(ptr, *ptr);
  799. }
  800.  
  801. /*
  802.  *  Convert a BSTR into a normal string.. copying the string into buf.
  803.  *  I use normal strings for internal storage, and convert back and forth
  804.  *  when required.
  805.  */
  806.  
  807. char *
  808. bstos(bstr)
  809. ubyte *bstr;
  810. {
  811.     static char buf[512];
  812.     static char *ptr = buf;
  813.  
  814.     if (ptr == buf)     /*  switch which buffer to use */
  815.     ptr = buf + 256;
  816.     else
  817.     ptr = buf;
  818.  
  819.     bstr = BTOC(bstr);
  820.     BMov(bstr+1,ptr,*bstr);
  821.     ptr[*bstr] = 0;
  822.     return(ptr);
  823. }
  824.  
  825. char *
  826. skipdevice(str)
  827. register char *str;
  828. {
  829.     char *base = str;
  830.  
  831.     while (*str && *str != ':')
  832.     ++str;
  833.     if (*str == 0)
  834.     str = base;
  835.     else
  836.     ++str;
  837.     return(str);
  838. }
  839.  
  840. /*
  841.  *  data = DoNetworkOp(&cmd, &len, data)
  842.  */
  843.  
  844. int
  845. DoNetworkOp(cmd, s, _slen, d, dlen, r, rlen)
  846. char cmd;
  847. int _slen;
  848. void *s;
  849. void *d;
  850. void *r;
  851. {
  852.     ubyte slen = _slen;
  853.     if (CHan) {
  854.     if (DWrite(CHan, &cmd, 1) < 0)
  855.         goto fail;
  856.     if (DWrite(CHan, &slen, 1) < 0)
  857.         goto fail;
  858.     if (DWrite(CHan, &dlen, 4) < 0)
  859.         goto fail;
  860.     if (DWrite(CHan, s, slen) < 0)
  861.         goto fail;
  862.  
  863.     if (dlen) {
  864.         if (DWrite(CHan, d, dlen) < 0)
  865.         goto fail;
  866.     }
  867.     if (r) {
  868.         if (DRead(CHan, r, rlen) != rlen)
  869.         goto fail;
  870.     }
  871.     return(0);
  872.     }
  873. fail:
  874.     if (CHan) {
  875.     DClose(CHan);
  876.     CHan = 0;
  877.     }
  878.     return(1);
  879. }
  880.  
  881. #ifndef LATTICE
  882.  
  883. #asm
  884.  
  885. _mygeta4:
  886.     far    data
  887.     lea    __H1_org+32766,a4
  888.     rts
  889.  
  890.     public    __H0_org
  891.  
  892.     dseg
  893.  
  894.     public    __H1_org
  895.  
  896.     cseg
  897. #endasm
  898.  
  899. #endif
  900.  
  901.  
  902. #ifdef DEBUG        /*    note, doesn't work w/ Lattice   */
  903.  
  904. /*
  905.  *                DEBUG CODE
  906.  */
  907.  
  908.  
  909.             /*    DEBUGGING            */
  910. PORT *Dbport;        /*    owned by the debug process    */
  911. PORT *Dback;        /*    owned by the DOS device driver    */
  912. MSG DummyMsg;        /*    Dummy message that debug proc can use    */
  913.  
  914. /*
  915.  *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  916.  *  devices from within a DOS device driver because they use the same
  917.  *  message port as the driver.  If you need to make such calls you must
  918.  *  create a port and construct the DOS messages yourself.  I do not
  919.  *  do this.  To get debugging info out another PROCESS is created to which
  920.  *  debugging messages can be sent.
  921.  *
  922.  *  You want the priority of the debug process to be larger than the
  923.  *  priority of your DOS handler.  This is so if your DOS handler crashes
  924.  *  you have a better idea of where it died from the debugging messages
  925.  *  (remember that the two processes are asyncronous from each other).
  926.  */
  927.  
  928. extern void debugproc();
  929.  
  930. dbinit()
  931. {
  932.     TASK *task = FindTask(NULL);
  933.  
  934.     Dback = CreatePort(NULL,NULL);
  935.     CreateProc("DEV_DB", task->tc_Node.ln_Pri+1, CTOB(debugproc), 4096);
  936.     WaitPort(Dback);                                /* handshake startup    */
  937.     GetMsg(Dback);                                  /* remove dummy msg     */
  938.     dbprintf("Debugger running V1.10, 2 November 1987\n");
  939.     dbprintf("Works with WORKBENCH!\n");
  940. }
  941.  
  942. dbuninit()
  943. {
  944.     MSG killmsg;
  945.  
  946.     if (Dbport) {
  947.     killmsg.mn_Length = 0;        /*    0 means die        */
  948.     PutMsg(Dbport,&killmsg);
  949.     WaitPort(Dback);            /*  He's dead jim!      */
  950.     GetMsg(Dback);
  951.     DeletePort(Dback);
  952.  
  953.     /*
  954.      *  Since the debug process is running at a greater priority, I
  955.      *  am pretty sure that it is guarenteed to be completely removed
  956.      *  before this task gets control again.  Still, it doesn't hurt...
  957.      */
  958.  
  959.     Delay(50);                  /*  ensure he's dead    */
  960.     }
  961. }
  962.  
  963. dbprintf(a,b,c,d,e,f,g,h,i,j)
  964. {
  965.     char buf[256];
  966.     MSG *msg;
  967.  
  968.     if (Dbport && !DBDisable) {
  969.     sprintf(buf,a,b,c,d,e,f,g,h,i,j);
  970.     msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
  971.     msg->mn_Length = strlen(buf)+1;     /*  Length NEVER 0  */
  972.     strcpy(msg+1,buf);
  973.     PutMsg(Dbport,msg);
  974.     }
  975. }
  976.  
  977. /*
  978.  *  BTW, the DOS library used by debugmain() was actually openned by
  979.  *  the device driver.    Note: DummyMsg cannot be on debugmain()'s stack
  980.  *  since debugmain() goes away on the final handshake.
  981.  */
  982.  
  983. void
  984. debugmain()
  985. {
  986.     MSG *msg;
  987.     short len;
  988.     void *fh;
  989.  
  990.     mygeta4();
  991.     Dbport = CreatePort(NULL,NULL);
  992.     fh = Open("con:0/0/640/100/debugwindow", 1006);
  993.     PutMsg(Dback, &DummyMsg);
  994.     for (;;) {
  995.     WaitPort(Dbport);
  996.     msg = GetMsg(Dbport);
  997.     len = msg->mn_Length;
  998.     if (len == 0)
  999.         break;
  1000.     --len;                  /*  Fix length up   */
  1001.     Write(fh, msg+1, len);
  1002.     FreeMem(msg,sizeof(MSG)+len+1);
  1003.     }
  1004.     Close(fh);
  1005.     DeletePort(Dbport);
  1006.     PutMsg(Dback,&DummyMsg);          /*  Kill handshake  */
  1007. }
  1008.  
  1009. /*
  1010.  *  The assembly tag for the DOS process:  CNOP causes alignment problems
  1011.  *  with the Aztec assembler for some reason.  I assume then, that the
  1012.  *  alignment is unknown.  Since the BCPL conversion basically zero's the
  1013.  *  lower two bits of the address the actual code may start anywhere around
  1014.  *  the label....  Sigh....  (see CreatProc() above).
  1015.  */
  1016.  
  1017. #asm
  1018.     public    _debugproc
  1019.     public    _debugmain
  1020.  
  1021.     cseg
  1022.     nop
  1023.     nop
  1024.     nop
  1025. _debugproc:
  1026.     nop
  1027.     nop
  1028.     movem.l D2-D7/A2-A6,-(sp)
  1029.     jsr    _debugmain
  1030.     movem.l (sp)+,D2-D7/A2-A6
  1031.     rts
  1032. #endasm
  1033.  
  1034.  
  1035. #endif
  1036.  
  1037.  
  1038.